#ifndef __LSZ_ASTRING_H__
#define __LSZ_ASTRING_H__

#include "LszTypes.h"

namespace Lsz
{

// String template for three types of strings:
// heap  ( with alloc/copy )
// stack ( automatic fixed size array, just copy )
// just a pointer ( no alloc/copy, fastest )

LSZCORE_EXPORT void AS_construct(const char *S, int heap, int bufsize, 
                  char mbuf[], char** mptr, int* mheap);

LSZCORE_EXPORT void AS_copyconstruct(char mbuf[], char **mptr, int *mheap, int bufsize,
                      const char *rptr, int rheap);

LSZCORE_EXPORT void AS_assign(char mbuf[], char **mptr, int mheap, int bufsize,
               const char *rptr);

LSZCORE_EXPORT void AS_destroy(char *mptr, int mheap, int bufsize);

LSZCORE_EXPORT int AS_compare(const char* l, const char* r);

class AString
{
public:
    enum {
        Shared=0,
        Onheap=1
    };

    AString(const char* s, int onheap=1) {
        AS_construct(s, onheap, 0, 
                     0, &_ptr, &_onheap);
    }

    AString(const AString& ri) {
        AS_copyconstruct(0, &_ptr, &_onheap, 0, ri._ptr, ri._onheap);
    }

    AString& operator=(const AString& ri) {
        if (&ri == this)
            return *this;
        AS_assign(0, &_ptr, _onheap, 0, ri._ptr);
        return *this;
    }

    virtual ~AString() {
        AS_destroy(_ptr, _onheap, 0);
    }

    bool operator==(const AString& r) const {
        return AS_compare(_ptr, r._ptr) == 0;
    }

    bool operator!=(const AString& r) const {
        return AS_compare(_ptr, r._ptr) != 0;
    }

    bool operator>(const AString& r) const {
        return AS_compare(_ptr, r._ptr)>0;
    }

    bool operator<(const AString& r) const {
        return AS_compare(_ptr, r._ptr)<0;
    }

    const char* str() const { return _ptr; }

    operator const char*() const { return _ptr; }

protected:
    AString(): _ptr(0), _onheap(0) {}
    char *_ptr;
    int   _onheap;
};

inline bool operator==(const AString& l, const char* r) {
    return AS_compare(l.str(), r) == 0;
}

inline bool operator!=(const AString& l, const char* r) {
    return AS_compare(l.str(), r) != 0;
}


template<int bufsize>
class AStringT : public AString
{
public:
    AStringT(const char *S="") {
        AS_construct(S, 0, bufsize, 
                    _buf, &_ptr, &_onheap);
    }

    AStringT(const AStringT& r) {
        AS_copyconstruct(_buf, &_ptr, &_onheap, bufsize,
            r.str(), 0);
        ASSERT(*this == r);
    }

#if 0
    AStringT(const AString& r) {
        AS_copyconstruct(_buf, &_ptr, &_onheap, bufsize,
                         r.str(), 0);
        ASSERT(*this == r);
    }
#endif

    AStringT& operator=(const AString& r) {
        if (&r == this)
            return *this;
        AS_assign(_buf, &_ptr, _onheap, bufsize, r.str());
        ASSERT(*this == r);
        return *this;
    }

    ~AStringT() {
        AS_destroy(_ptr, _onheap, bufsize);
    }
private:
    char  _buf[bufsize+1];
};

typedef AStringT<32> AString32;
typedef AStringT<64> AString64;

#define ASharedString(Var, Str) AString Var(Str, 0);

}

#endif // __LSZ_ASTRING_H__
